2010-09-09 5 views
1

У меня есть два интерфейса, подобного этим:Класс, который реализует интерфейс с IList другого свойства интерфейса ... как?

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 в моем классе?

ответ

6

Ваш интерфейс требует, чтобы класс реализации предоставлял свойство, которое имеет тип 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

Я собирался опубликовать тот же самый код :) –

0

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.

1

Это потому, что ваш интерфейс 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

Я не уверен, если я бы назвал это дубликат the question from yesterday но ...

.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 Безразлично 't ссылается на ту же коллекцию, что и prop2.

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

+1

'Enumerable.Cast' производит' IEnumerable ', а не' IList '. На самом деле это не подходит для решения проблемы, так как вам придется устанавливать 'prop2' равным новой ссылке независимо от того, как вы это делаете. –

+0

@ Адам Робинсон - Это определенно не идеально. И да, если вы пытались добавить элементы в IMyInterface2.prop2, у вас возникли проблемы. Если OP использует .NET 4, вызов Cast() является избыточным, поскольку вы можете использовать новые функции ковариации/контравариантности. –

+0

@JustinNiessner: для ['IList '] (http://msdn.microsoft.com/en-us/library/5y536ey6%28v=vs.110%29.aspx)? Вряд ли так; ковариация/контравариантность там не используются, поскольку 'T' используется как для ввода, так и для вывода в этом интерфейсе. Если бы это был просто «IEnumerable », да. –

0

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

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 <IMyInterface2> в prop2, но MyClass2 не может справиться с этим. Вот почему вы не можете реализовать записываемое свойство, как вы предложили.