The following code:
public interface ISomeData { IEnumerable<string> Data { get; } } public class MyData : ISomeData { private List<string> m_MyData = new List<string>(); public List<string> Data { get { return m_MyData; } } }
Produces the following error:
error CS0738: 'InheritanceTest.MyData' does not implement interface member 'InheritanceTest.ISomeData.Data'. 'InheritanceTest.MyData.Data' cannot implement 'InheritanceTest.ISomeData.Data' because it does not have the matching return type of 'System.Collections.Generic.IEnumerable'.
Since a List<T> implements IEnumerable<T>, one would think that my class would implement the interface. Can someone explain what the rationale is for this not compiling?
As I can see it, there are two possible solutions:
Now suppose I also have the following code:
public class ConsumerA { static void IterateOverCollection(ISomeData data) { foreach (string prop in data.MyData) { /*do stuff*/ } } } public class ConsumerB { static void RandomAccess(MyData data) { data.Data[1] = "this line is invalid if MyPropList return an IEnumerable<string>"; } }
I could change my interface to require IList to be implemented (option 1), but that limits who can implement the interface and the number of classes that can be passed into ConsumerA. Or, I could change implementation (class MyData) so that it returns an IEnumerable instead of a List (option 2), but then ConsumerB would have to be rewritten.
This seems to be a shortcoming of C# unless someone can enlighten me.
Answers. By definition of what an interface is it is impossible to return an interface because interfaces cannot be allocated; there cannot be anything to return.
An interface can extend any number of interfaces but one interface cannot implement another interface, because if any interface is implemented then its methods must be defined and interface never has the definition of any method.
Explanation: In case of adapter class, we can implement only required methods of any interface.
Like a class, an interface can have methods and variables, but the methods declared in an interface are by default abstract (only method signature, no body). Interfaces specify what a class must do and not how.
Unfortunately, the return type must match. What you are looking for is called 'return type covariance' and C# doesn't support that.
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=90909
Eric Lippert, senior developer on C# Compiler team, mentions on his blog that they don't plan to support return type covariance.
"That kind of variance is called "return type covariance". As I mentioned early on in this series, (a) this series is not about that kind of variance, and (b) we have no plans to implement that kind of variance in C#. "
http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx
It's worth reading Eric's articles on covariance and contravariance.
http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
For what you want to do you'll probably want to implement the interface explicitly with a class (not interface) member that returns the List instead of IEnumerable...
public class MyData : ISomeData { private List<string> m_MyData = new List<string>(); public List<string> Data { get { return m_MyData; } } #region ISomeData Members IEnumerable<string> ISomeData.Data { get { return Data.AsEnumerable<string>(); } } #endregion }
Edit: For clarification, this lets the MyData class return a List when it is being treated as an instance of MyData; while still allowing it to return an instance of IEnumerable when being treated as an instance of ISomeData.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With