以下代码:
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; } }
}
Run Code Online (Sandbox Code Playgroud)
产生以下错误:
错误CS0738:'InheritanceTest.MyData'未实现接口成员'InheritanceTest.ISomeData.Data'.'InheritanceTest.MyData.Data'无法实现'InheritanceTest.ISomeData.Data',因为它没有匹配的返回类型'System.Collections.Generic.IEnumerable'.
由于List <T>实现了IEnumerable <T>,因此可以认为我的类将实现该接口.有人可以解释一下这个不编译的理由是什么吗?
我可以看到,有两种可能的解决方案:
现在假设我也有以下代码:
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>";
}
}
Run Code Online (Sandbox Code Playgroud)
我可以更改我的接口以要求实现IList(选项1),但是这限制了谁可以实现接口以及可以传递给ConsumerA的类的数量.或者,我可以更改实现(类MyData),以便它返回IEnumerable而不是List(选项2),但然后必须重写ConsumerB.
这似乎是C#的一个缺点,除非有人可以启发我.
STW*_*STW 27
对于您想要做的事情,您可能希望使用返回List而不是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
}
Run Code Online (Sandbox Code Playgroud)
编辑: 为了澄清,这使MyData类在被视为MyData的实例时返回List; 同时仍然允许它在被视为ISomeData的实例时返回IEnumerable的实例.
Sol*_*ogi 24
不幸的是,返回类型必须匹配.您正在寻找的是"返回类型协方差",C#不支持这一点.
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=90909
C#Compiler团队的高级开发人员Eric Lippert在他的博客中提到他们不打算支持返回类型的协方差.
"这种方差被称为"返回类型协方差".正如我在本系列的早期提到的那样,(a)这个系列不是关于那种方差,(b)我们没有计划实现这种方差. C#. "
值得阅读Eric关于协方差和逆变的文章.
http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
What if you accessed your MyData object trough the ISomeData interface? In that case, IEnumerable could be of an underlying type not assignable to a List.
IEnumerable<string> iss = null;
List<string> ss = iss; //compiler error
Run Code Online (Sandbox Code Playgroud)
EDIT:
I understand what you mean from your comments.
Anyway, what I would do in your case would be:
public interface ISomeData<T> where T: IEnumerable<string>
{
T Data { get; }
}
public class MyData : ISomeData<List<string>>
{
private List<string> m_MyData = new List<string>();
public List<string> Data { get { return m_MyData; } }
}
Run Code Online (Sandbox Code Playgroud)
Converting to generic Interface with appropriate constraint offers I think the best of both flexibility and readability.
归档时间: |
|
查看次数: |
7000 次 |
最近记录: |