The following code:
public interface ISomeData
{
IEnumerable Data { get; }
}
public class MyData : ISomeData
{
private List
I have run into similar situations and want to give a more concrete example of why this is not allowed. Generic parts of my app deal with an interface that contains properties, and provides data through that interface to another part of the application that contains concrete classes implementing these interfaces.
The goal I think is similar to yours: the conrete classes to have more functionality, and the interface provides the absolute minimum needed for the generic part of the application. It is a good practice for the Interface to expose the least amount of functionality needed, because it maximizes compatibility/reuseability. I.e. it doesn't require an implementer of the interface to implement more than is needed.
However consider if you had a setter on that property. You create an instance of your concrete class, and pass it to some generic helper that takes an ISomeData. In that helper's code, they are working with an ISomeData. Without any type of generic T where T:new() or factory pattern, they can't create new instances to go into Data that match your concrete implementation. They simply return a list that implements IEnumerable:
instanceISomeData.Data = new SomeOtherTypeImplementingIEnumerable();
If SomeOtherTypeImplementingIEnumerable doesn't inherit List, but you've implemented .Data as a List, then this is an invalid assignment. If the compiler allowed you to do this, then scenarios like this would crash at runtime because SomeOtherTypeImplementingIEnumerable can't be cast to List. However, in the context of this helper working with ISomeData, it hasn't violated the ISomeData interface in anyway, and the assignment of any type supporting IEnumerable to .Data should be valid. So your implementation, if the compiler allowed it, could break perfectly good code working with the Interface.
This is why you can't implement .Data as a derived type. You are more tightly constraining the implementation of .Data to only except List, instead of any IEnumerable. Thus while the interface says "any IEnumerable is allowed", your concrete implementation would cause pre-existing code supporting ISomeData to suddenly break when working with your implementation of the interface.
Of course you don't really run into this scenario with only a getter, but it would complicate things to allow it in get scenarios but not otherwise.
I usually go with Jake's solution or Alioto's solution, depending on how picky I am feeling at the moment.