Class that implements an interface with IList of another interface property...how to?
I have two interfaces like these:
public interface IMyInterface1
{
string prop1 { get; set; }
string prop2 { get; set; }
}
public interface IMyInterface2
{
string prop1 { get; set; }
IList<IMyInterface1> prop2 { get; set; }
}
I have defined two classes that implement the interfaces:
public class MyClass1 : IMyInterface1
{
public string prop1 {get; set;}
public string prop开发者_运维百科2 {get; set;}
}
public class MyClass2 : IMyInterface2
{
public string prop1 {get; set;}
public IList<MyClass1> prop2 {get; set;}
}
but when I build the code I have the following error message:
'ClassLibrary1.MyClass2' does not implement interface member 'ClassLibrary1.IMyInterface2.prop2'. 'ClassLibrary1.MyClass2.prop2' cannot implement 'ClassLibrary1.IMyInterface2.prop2' because it does not have the matching return type of 'System.Collections.Generic.IList'
How can I do to implement the "IList prop2" of IMyInterface2 on my class?
Your interface requires that the implementing class provide a property that is of type IList<IMyInterface1>
, not IList<class that implements IMyInterface1>
.
You'll need to make IMyInterface2
generic if you want this to work:
public interface IMyInterface2<T> where T : IMyInterface1
{
string prop1 { get; set; }
IList<T> prop2 { get; set; }
}
Then MyClass2
becomes:
public class MyClass2 : IMyInterface2<MyClass1>
{
public string prop1 {get; set;}
public IList<MyClass1> prop2 {get; set;}
}
This is because your interface MyInterface2
has a property which is a generic list of type IInterface1
and in the class that implements this interface i.e. MyClass2
you have declared the property as being a list of type MyClass1
.
To fix, either change the class definition of Prop2
to be a list of MyInterface1
or change the interface definition of Prop2
to be a list of MyClass1
.
e.g.
public interface MyInterface2
{
public IList<MyInterface1> Prop2 { get; set; }
}
public class MyClass2 : MyInterface2
{
public IList<MyInterface1> Prop2 { get; set; }
}
I'm not sure if I'd call this a duplicate of the question from yesterday but...
.NET doesn't support return type covariance. That means you can't return a derived type from a class that implements an interface that requires a more generic type.
The workaround is to explicitly implement the member of the interface giving you trouble:
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(); }
}
}
In this case, though, explicitly implementing the interface like that will cause issues if you try to call IMyInterface.prop2.Add()
since IMyInterface.prop2
doesn't reference the same collection as prop2 anymore.
The other way to solve the problem would be to implement Adam's suggestion and make IMyInterface2
generic so you can supply any type that implements IMyInterface1
.
MyClass2
must implement the property as it's declared in the interface:
public class MyClass2 : IMyInterface2
{
public string prop1 {get; set;}
public IList<IMyInterface1> prop2 {get; set;}
}
Even though MyClass1
implements IMyInterface1
, it may cause problems in cases such as:
IMyInterface2 myInterface2 = new MyClass2();
myInterface2.prop2.Add(new OtherImplementationOfIMyInterface1());
Anyone uses the class expects to be able to assign any instance which implements IMyInterface1
but the class expects concrete instances of MyClass1
.
The issue with trying to implement the code like that is this. If the compiler allowed you to compile that code, then you could write code like this:
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>();
The interface should allow you to put any IList<IMyInterface2> into prop2, but MyClass2 can't handle that. That's why you can't implement a writable property as you have suggested.
精彩评论