Класс, который реализует интерфейс с IList другого свойства интерфейса ... как? - PullRequest
2 голосов
/ 09 сентября 2010

У меня есть два таких интерфейса:

public interface IMyInterface1
{
    string prop1 { get; set; }
    string prop2 { get; set; }
}

public interface IMyInterface2
{
    string prop1 { get; set; }
    IList<IMyInterface1> prop2 { get; set; }
}

Я определил два класса, которые реализуют интерфейсы:

public class MyClass1 : IMyInterface1
{
     public string prop1 {get; set;}
     public string prop2 {get; set;}
}

public class MyClass2 : IMyInterface2
{
     public string prop1 {get; set;}
     public IList<MyClass1> prop2 {get; set;}
}

но при сборке кода появляется следующее сообщение об ошибке:

ClassLibrary1.MyClass2 не реализует элемент интерфейса ClassLibrary1.IMyInterface2.prop2. ClassLibrary1.MyClass2.prop2 не может реализовать ClassLibrary1.IMyInterface2.prop2, поскольку у него нет соответствующего возвращаемого типа System.Collections.Generic.IList '

Как я могу реализовать "IList prop2" IMyInterface2 в моем классе?

Ответы [ 5 ]

7 голосов
/ 09 сентября 2010

Ваш интерфейс требует, чтобы реализующий класс предоставлял свойство типа IList<IMyInterface1>, а не IList<class that implements IMyInterface1>.

Вам нужно сделать IMyInterface2 универсальным, если вы хотите, чтобы это работало:

public interface IMyInterface2<T> where T : IMyInterface1
{
    string prop1 { get; set; }
    IList<T> prop2 { get; set; }
}

Тогда MyClass2 становится:

public class MyClass2 : IMyInterface2<MyClass1>
{
     public string prop1 {get; set;}
     public IList<MyClass1> prop2 {get; set;}
}
1 голос
/ 09 сентября 2010

Это потому, что ваш интерфейс MyInterface2 имеет свойство, которое является общим списком типа IInterface1, и в классе, который реализует этот интерфейс, т.е. MyClass2, вы объявили свойство как список типа MyClass1.

Чтобы исправить, измените определение класса Prop2 на список MyInterface1 или измените определение интерфейса Prop2 на список MyClass1.

Например

public interface MyInterface2
{
    public IList<MyInterface1> Prop2 { get; set; }
}

public class MyClass2 : MyInterface2
{
    public IList<MyInterface1> Prop2 { get; set; }
}
1 голос
/ 09 сентября 2010

Я не уверен, если бы я назвал это дубликатом вчерашнего вопроса , но ...

.NET не поддерживает ковариацию возвращаемого типа.Это означает, что вы не можете вернуть производный тип из класса, который реализует интерфейс, для которого требуется более общий тип.

Обходной путь заключается в явной реализации члена интерфейса, что вызывает проблемы:

public class MyClass2 : IMyInterface2
{
    public string prop1 { get; set; }
    public IList<MyClass1> prop2 { get; set; }
    public IList<IMyInterface1> IMyInterface2.prop2
    {
        get { return prop2.Cast<IMyInterface1>.ToList(); }
        set { prop2 = value.Cast<MyClass1>().ToList(); }
    }
}

В этом случае, однако, явная реализация подобного интерфейса вызовет проблемы, если вы попытаетесь вызвать IMyInterface.prop2.Add(), поскольку IMyInterface.prop2 больше не ссылается на ту же коллекцию, что и prop2.

Другойспособ решить эту проблему - реализовать предложение Адама и сделать IMyInterface2 универсальным, чтобы вы могли предоставить любой тип, который реализует IMyInterface1.

0 голосов
/ 09 сентября 2010

Проблема с попыткой реализовать подобный код заключается в следующем.Если компилятор позволил вам скомпилировать этот код, вы могли бы написать код, подобный следующему:

public class MyClass3 : IMyInterface1 
{ 
    public string prop1 {get; set;} 
    public string prop2 {get; set;} 
} 

...

MyClass2 mc2 = new MyClass2();
IMyInterface2 mi2 = mc2;
mi2.prop2 = new List<MyClass3>();

Интерфейс должен позволить вам поместить любой IListв prop2, но MyClass2 не может справиться с этим.Вот почему вы не можете реализовать доступное для записи свойство, как вы предлагали.

0 голосов
/ 09 сентября 2010

MyClass2 должно реализовывать свойство, как оно объявлено в интерфейсе:

public class MyClass2 : IMyInterface2
{
     public string prop1 {get; set;}
     public IList<IMyInterface1> prop2 {get; set;}
}

Даже если MyClass1 реализует IMyInterface1, это может вызвать проблемы в таких случаях, как:

IMyInterface2 myInterface2 = new MyClass2();
myInterface2.prop2.Add(new OtherImplementationOfIMyInterface1());

Любой, кто использует класс, ожидает, что сможет назначить любой экземпляр, который реализует IMyInterface1, но класс ожидает конкретные экземпляры MyClass1.

...